package developerworks.jetty6;

import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONException;
import org.json.JSONObject;

import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSubscriber;
import javax.naming.InitialContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.mortbay.util.ajax.Continuation;
import javax.jms.*;
import java.io.Serializable;


//this is the address book for a single application
public class ApplicationAddressBook  implements MessageListener {
	
	static private Hashtable<String, Domain> domain_hash = new Hashtable<String, Domain>();
	static private Hashtable<String, Domain> user_hash = new Hashtable<String, Domain>();
	
	
	
	static private Hashtable<String, Continuation> continuation_hash = new Hashtable<String, Continuation>();
	static public Pattern pattern = Pattern.compile("https?://(?:www\\.)?([^/]*)([^#\\?]*)");

	
	public ApplicationAddressBook(){
		
	}
	
	
	static public void send(Serializable s){
		Timey t = new Timey();
		CrudMessage.subscriber.publish(s);
		t.end("Publish");
	}
	
	
	static public String getDomainName(HttpServletRequest req){
		return getDomainName(req.getHeader("Referer"));
	}

	
	
	static public String getDomainName(String url){
		String domain_name = "jabbify.com";

		Matcher matcher = pattern.matcher(url);
		boolean matchFound = matcher.find();
		if(matchFound){
			domain_name = matcher.group(1).toLowerCase();
		}else{
			System.out.println("Error parsing!!!!");
		}
		return domain_name;
	}
	
	static Domain getDomain(String domain_name){
		Domain domain = domain_hash.get(domain_name);
		if(domain == null){
			  domain = new Domain();
			  domain_hash.put(domain_name, domain);
		}
		return domain;
	}
	
	/**
	 * Adds a user to this applications Address Book (basically adds
	 * @param u
	 */
	static void addInbox(Inbox i){
		Domain domain = getDomain(i.domain());
		domain.addInbox(i);
		synchronized(user_hash){
			user_hash.put(i.call_id, domain);
		}
		
	}
	static void removeInbox(Inbox i){
		Domain domain = getDomain(i.domain());
		domain.removeInbox(i);
		synchronized(user_hash){
			user_hash.remove(i.call_id);
		}
	}
	/**
	 * Needs to add continuation to 2 places
	 * @param continuation
	 * @param caller_id
	 * @param domain
	 */
	static void addContinuation(Continuation c, HttpSession session, int timeoutSec){
		Inbox i = (Inbox) session.getAttribute("Inbox");
		System.out.println("Continuation for "+i.domain());
		Domain domain = getDomain(i.domain());
		domain.addContinuation(c, session, timeoutSec);
	}
	//needs to resume 1 continuation, and remove it from
	//the domain's list of continuations
	static void resumeContinuation(HttpSession session ){
		Inbox i = (Inbox) session.getAttribute("Inbox");
		Domain domain = getDomain(i.domain());
		domain.resumeContinuation(i.user);
	}
	
	//basically sends to everyone
	static void sendToDomain(CrudMessage o){
		Domain d  = getDomain(o.domainName());
		d.newCRUDAll(o);
	}
	//only sends a message to one person, checks if they are there
	static void sendToUser(CrudMessage o){
		Domain d;
		synchronized (user_hash) {
			d = user_hash.get(o.callID());
		}
		if(d == null) return;
		d.newCRUDOne(o, o.callID());
	}
	
	public void onMessage(Message msg){
		System.out.println("Got message application address book");
		try
        {
			ObjectMessage tm = (ObjectMessage)msg;
			CrudMessage cm = (CrudMessage) tm.getObject();
			if(cm.isGroup()){
				sendToDomain(cm);
			}else{
				sendToUser(cm);
			}
        }
        catch (Throwable t)
        {
            t.printStackTrace();
        }
	}
	
	
}
